package com.snowball.demo.exception;

import com.snowball.demo.exception.enums.ResultCode;
import com.snowball.springboot.core.dto.ResponseInfo;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.core.MethodParameter;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * Description:
 *
 * @Author: genezhao
 * @Date: 2018-06-27
 */
@ControllerAdvice
@ResponseBody
public class ExceptionHandlerAdvice implements ResponseBodyAdvice {

    private ThreadLocal<Object> modelHolder = new ThreadLocal<>();

    @ExceptionHandler(BusinessException.class)
    public ResponseInfo businessException(BusinessException e, HttpServletRequest request){
        return new ResponseInfo()
                .setCode(e.getCode())
                .setMessage(e.getMessage())
                .setPath(request.getRequestURI())
                .setTimestamp(System.currentTimeMillis());
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public ResponseInfo mySQLIntegrityConstraintViolationException(DuplicateKeyException e, HttpServletRequest request) {
        return new ResponseInfo()
                .setCode(ResultCode.PARAMETER_IDX_ERROR.getCode())
                .setMessage(ResultCode.PARAMETER_IDX_ERROR.getMsg())
                .setError(e.getCause().getMessage())
                .setException(e.toString())
                .setPath(request.getRequestURI())
                .setTimestamp(System.currentTimeMillis());
    }

    @ExceptionHandler(MyBatisSystemException.class)
    public ResponseInfo tooManyResultException(MyBatisSystemException e, HttpServletRequest request) {
        return new ResponseInfo()
                .setCode(ResultCode.RESULT_ERROR.getCode())
                .setMessage(ResultCode.RESULT_ERROR.getMsg())
                .setError(e.getCause().getMessage())
                .setException(e.toString())
                .setPath(request.getRequestURI())
                .setTimestamp(System.currentTimeMillis());
    }

    @ExceptionHandler(value = Exception.class)
    public ResponseInfo unknownException(Exception e, HttpServletRequest request) {
        return new ResponseInfo()
                .setCode(ResultCode.UNKNOWN_ERROR.getCode())
                .setMessage(ResultCode.UNKNOWN_ERROR.getMsg())
                .setException(e.toString())
                .setPath(request.getRequestURI())
                .setTimestamp(System.currentTimeMillis());
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        modelHolder.remove();
        return o;
    }
}
